/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pe.com.cotelasa.scp.controlador;

import com.thoughtworks.xstream.XStream;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import pe.com.cotelasa.common.controlador.MBGenerico;
import static pe.com.cotelasa.common.controlador.MBGenerico.mostrarError;
import static pe.com.cotelasa.common.controlador.MBGenerico.mostrarMensaje;
import pe.com.cotelasa.scp.common.IObserver;
import pe.com.cotelasa.scp.controlador.backingBean.BKCajaChica;
import pe.com.cotelasa.scp.controlador.backingBean.BKDocumentoSustentador;
import pe.com.cotelasa.scp.controlador.backingBean.BKMovimientoCajaChica;
import pe.com.cotelasa.scp.controlador.comando.ComandoGuardar;
import pe.com.cotelasa.scp.dominio.common.Constantes;
import pe.com.cotelasa.scp.dominio.common.ESTADO_REGISTRO;
import pe.com.cotelasa.scp.dominio.common.URLPaginacion;
import pe.com.cotelasa.scp.dominio.common.util.UtilitarioFecha;
import pe.com.cotelasa.scp.dominio.excepcion.ServiceException;
import pe.com.cotelasa.scp.dominio.service.IServicioCajaChica;
import pe.com.cotelasa.scp.dominio.service.IServicioCompraFacturacion;
import pe.com.cotelasa.scp.dominio.service.IServicioCorrelativoDocumento;
import pe.com.cotelasa.scp.dominio.service.IServicioDocumentoSustentador;
import pe.com.cotelasa.scp.dominio.service.IServicioMovimientoCajaChica;
import pe.com.cotelasa.scp.dominio.service.IServicioMovimientoCuentaBancaria;
import pe.com.cotelasa.scp.dominio.service.IServicioSede;
import pe.com.cotelasa.scp.dominio.service.IServicioTipoDocumento;
import pe.com.cotelasa.scp.dominio.service.IServicioTipoMoneda;
import pe.com.cotelasa.scp.entidad.CajaChica;
import pe.com.cotelasa.scp.entidad.CompraFacturacion;
import pe.com.cotelasa.scp.entidad.CorrelativoDocumento;
import pe.com.cotelasa.scp.entidad.DocumentoSustentador;
import pe.com.cotelasa.scp.entidad.MovimientoCajaChica;
import pe.com.cotelasa.scp.entidad.MovimientoCuentaBancaria;
import pe.com.cotelasa.scp.entidad.Proveedor;
import pe.com.cotelasa.scp.entidad.Sede;
import pe.com.cotelasa.scp.entidad.TipoDocumento;
import pe.com.cotelasa.scp.entidad.TipoMoneda;
import pe.com.cotelasa.seguridad.controlador.backingBean.BKSession;

@SuppressWarnings("serial")
@Named(value = "MBCajaChica")
@Scope("request")
public class MBCajaChica extends MBGenerico implements IMantenedor, Serializable, IObserver {

    private static final long serialVersionUID = -8863078593063550746L;
    private static Logger logger = Logger.getLogger(MBCajaChica.class);
    @Inject
    private BKCajaChica bkCajaChica;
    @Inject
    private BKMovimientoCajaChica bkMovimientoCajaChica;
    @Inject
    private BKDocumentoSustentador bkDocumentoSustentador;
    @Inject
    private IServicioSede servicioSede;
    @Inject
    private IServicioMovimientoCuentaBancaria servicioMovimientoCuenta;
    @Inject
    private IServicioCajaChica servicioCajaChica;
    @Inject
    private IServicioMovimientoCajaChica servicioMovCajaChica;
    @Inject
    private IServicioDocumentoSustentador servicioDocSustentador;
    @Inject
    private IServicioCompraFacturacion servicioCompraFacturacion;
    @Inject
    private IServicioTipoMoneda servicioMoneda;
    @Inject
    private MBComponenteFindProveedor mbComponenteFindProveedor;
    @Autowired
    BKSession session;
    private String URL;

    public String mostrarMantenimiento() {

        bkCajaChica.setCajaChicaBusqueda(new CajaChica());

        bkCajaChica.getCajaChicaBusqueda().setCodigoCaja("");
        bkCajaChica.getCajaChicaBusqueda().setEstadoCaja("");
        bkCajaChica.getCajaChicaBusqueda().setIdSede(new Sede(0));
        bkCajaChica.getCajaChicaBusqueda().setIdMovimientoCuentaBancaria(new MovimientoCuentaBancaria(0));
        bkCajaChica.setListaEstados(new ArrayList<String>());
        for (Enum e : CajaChica.ESTADO_CAJA_CHICA.values()) {
            bkCajaChica.getListaEstados().add(e.name());
        }
        try {

            if (session.getUsuario().getIdRol().getNombre().contains("ADMINISTRADOR")) {
                bkCajaChica.setMostrarListaSedes(servicioSede.listaSedePorEmpresa(session.getEmpresa().getId()));
            } else {
                bkCajaChica.getCajaChicaBusqueda().setIdSede(session.getSede());
            }

            bkCajaChica.setMostrarListaCajaChica(null);

        } catch (ServiceException e) {
            System.out.println(e.getMessage());
            mostrarError("Ocurrieron algunos problemas al actualizar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

        return URLPaginacion.CajaChica.URL_CONSULTAR_CAJA_CHICA;
    }

    public void buscarListaCajaChica() {

        try {

            if (bkCajaChica.getCajaChicaBusqueda().getIdSede().getId() == 0) {
                bkCajaChica.getCajaChicaBusqueda().getIdSede().setIdEmpresa(session.getEmpresa());
            }
            bkCajaChica.setMostrarListaCajaChica(this.servicioCajaChica.listarCajaChicaPorFiltro(bkCajaChica.getCajaChicaBusqueda(), bkCajaChica.getFechaInicio(), bkCajaChica.getFechaFinal()));

        } catch (ServiceException e) {

            mostrarError("Ocurrieron algunos problemas al cargar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

    }

    @Override
    public String nuevo() {
        bkCajaChica.setComando(new ComandoGuardar(this));
        bkCajaChica.setVerFormulario(false);
        bkCajaChica.setCajaChicaFormulario(new CajaChica());

        bkCajaChica.getCajaChicaFormulario().setIdSede(session.getSede());
        bkCajaChica.getCajaChicaFormulario().setIdMovimientoCuentaBancaria(new MovimientoCuentaBancaria(0));
        try {
            bkCajaChica.getCajaChicaFormulario().setMoneda(servicioMoneda.conseguirTipoMonedaPorId(Constantes.TipoMoneda.SOLES));
            bkCajaChica.setMostrarListaCheques(servicioMovimientoCuenta.listarTodosCheques(session.getEmpresa().getId()));

            return URLPaginacion.CajaChica.URL_REGISTRAR_CAJA_CHICA;

        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al cargar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);

            return URLPaginacion.CajaChica.URL_CONSULTAR_CAJA_CHICA;
        }

    }

    @Override
    public String guardar() {

        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();

        try {
            if (cajaChica.getIdMovimientoCuentaBancaria().getId() == 0) {
                mostrarError("Debe seleccionar el número de cheque.");

                URL = URLPaginacion.CajaChica.URL_REGISTRAR_CAJA_CHICA;
            } else {
                cajaChica.setNombre(nombreCajaChica2(cajaChica.getIdSede()));
                cajaChica.setEstadoCaja(CajaChica.ESTADO_CAJA_CHICA.ABIERTA.getValor());
                cajaChica.setUsrCreacion(session.getUsuario().getUsuario());
                cajaChica.setFecCreacion(new Date());

                cajaChica.setSaldoCaja(cajaChica.getMontoApertura());
            }

            servicioCajaChica.registrarCajaChica(cajaChica);

            mostrarMensaje("Se guardó satisfactoriamente los datos de la Caja Chica ");
            
            URL = URLPaginacion.CajaChica.URL_CONSULTAR_CAJA_CHICA;

            //actualizar el estado del movimiento de de cuenta bancaria, en este caso el cheque que se destina
            //para caja chica 

            MovimientoCuentaBancaria movCta = servicioMovimientoCuenta.conseguirMovimientoPorId(cajaChica.getIdMovimientoCuentaBancaria().getId());
            movCta.setEstadoMovimiento(MovimientoCuentaBancaria.ESTADO_MOV_CUENTA_BANCARIA.CERRADO.getValor());
            movCta.setFecModificacion(new Date());
            movCta.setUsrModificacion(session.getUsuario().getUsuario());
            movCta.setSaldo(BigDecimal.ZERO);
            movCta.setFechaCierre(cajaChica.getFechaApertura());
            servicioMovimientoCuenta.actualizarMovCtaBancaria(movCta);
            
            buscarListaCajaChica();

        } catch (Exception e) {
            mostrarError("Ocurrieron algunos problemas al guardar la información. Vuelva a intentar.");
            System.err.println(e);

            URL = URLPaginacion.CajaChica.URL_REGISTRAR_CAJA_CHICA;
            logger.error(e.getMessage(), e);
        }
        return URL;

    }

    @Override
    public String actualizar() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void buscarMovCB() {

        try {
            if (bkCajaChica.getCajaChicaFormulario().getIdMovimientoCuentaBancaria().getId() != 0) {
                MovimientoCuentaBancaria mov = servicioMovimientoCuenta.conseguirMovimientoPorId(bkCajaChica.getCajaChicaFormulario().getIdMovimientoCuentaBancaria().getId());
                if (mov.getIdCuentaBancaria().getIdTipoMoneda().getId() == Constantes.TipoMoneda.SOLES) {
                    bkCajaChica.getCajaChicaFormulario().setMontoApertura(mov.getMonto());
                } else {
                    bkCajaChica.getCajaChicaFormulario().setMontoApertura(null);
                }

                bkCajaChica.getCajaChicaFormulario().setFechaEmisionCheque(mov.getFechaMovimiento());
                bkCajaChica.getCajaChicaFormulario().setNumeroDocumento(mov.getNumFormaMovimiento());
                bkCajaChica.getCajaChicaFormulario().setIdMovimientoCuentaBancaria(mov);

                bkCajaChica.setBancoFormulario(mov.getIdCuentaBancaria().getIdBanco().getNombre());


            } else {
                bkCajaChica.getCajaChicaFormulario().setMontoApertura(null);
                bkCajaChica.getCajaChicaFormulario().setFechaEmisionCheque(null);
                bkCajaChica.getCajaChicaFormulario().setNumeroDocumento(null);
                bkCajaChica.setBancoFormulario(null);
                bkCajaChica.getCajaChicaFormulario().setIdMovimientoCuentaBancaria(new MovimientoCuentaBancaria(0));

            }
        } catch (ServiceException e) {
            logger.error(e.getMessage(), e);
            mostrarError("Ocurrio un error al cargar la informacion.");
        }

    }

    public void calcularMonto() {
        bkCajaChica.getCajaChicaFormulario().setMontoApertura(
                bkCajaChica.getCajaChicaFormulario().getIdMovimientoCuentaBancaria().getMonto().multiply(bkCajaChica.getCajaChicaFormulario().getTipoCambio()));
    }

    public String nombreCajaChica2(Sede sedeOrigen) {

        String nombreBase;
        String format = "%1$03d";

        nombreBase = sedeOrigen.getNombre().substring(0, 4);
        nombreBase += "-" + Integer.toString(UtilitarioFecha.obtenerAnioActual()) + "-";

        try {
            bkCajaChica.setListaCajaChicaPorSede(servicioCajaChica.listarCajaChicaPorSede(sedeOrigen, nombreBase));
        } catch (ServiceException e) {
            logger.error(e.getMessage(), e);
            mostrarError("Ocurrió un error al buscar las cajas de la sede.");
        }
        if (bkCajaChica.getListaCajaChicaPorSede().isEmpty()) {
            nombreBase += "001";

        } else {
            nombreBase += String.format(format, bkCajaChica.getListaCajaChicaPorSede().size() + 1);

        }

        return nombreBase;
    }

    @Override
    public String ver() {

        bkMovimientoCajaChica.setMovCajaChicaBusqueda(new MovimientoCajaChica());

        try {

            CajaChica cajaChica = servicioCajaChica.conseguirCajaChicaPorId(bkCajaChica.getCajaChicaFormulario().getId());

            bkCajaChica.setCajaChicaFormulario(cajaChica);
            bkCajaChica.setVerResumenCaja(verificaMovCerrados(cajaChica));
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));



        } catch (ServiceException e) {

            mostrarError("Ocurrieron algunos problemas al cargar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

        bkMovimientoCajaChica.setVerFormulario(true);

        return URLPaginacion.CajaChica.URL_VER_CAJA_CHICA;
    }

    public void cerrarCajaChica() {
        try {
            CajaChica cajaChica = servicioCajaChica.conseguirCajaChicaPorId(bkCajaChica.getCajaChicaSeleccionado().getId());

            if (verificaMovCerrados(cajaChica)) {

                cajaChica.setEstadoCaja(CajaChica.ESTADO_CAJA_CHICA.CERRADA.getValor());
                cajaChica.setFechaCierre(new Date());
                cajaChica.setUsrModificacion(session.getUsuario().getUsuario());
                cajaChica.setFecModificacion(new Date());

                try {

                    servicioCajaChica.actualizarCajaChica(cajaChica);
                    buscarListaCajaChica();
                    mostrarMensaje("Se cerró la caja chica satisfactoriamente");

                } catch (ServiceException e) {
                    mostrarError("Ocurrieron algunos problemas. Vuelva a intentar");
                    logger.error(e.getMessage(), e);
                }

            } else {

                mostrarError("No se cerró la caja. Aún faltan cerrar movimientos o no se ha creado movimientos");
            }
        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

    }

    public boolean verificaMovCerrados(CajaChica cajaChica) {

        boolean exito = false;
        int tamLista = 0;
        int cont = 0;

        try {
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));
            tamLista = this.bkMovimientoCajaChica.getListaMovCajaChicaActivas().size();
            for (MovimientoCajaChica movCajaChica : this.bkMovimientoCajaChica.getListaMovCajaChicaActivas()) {
                if (movCajaChica.getEstadoMovimiento().equals(CajaChica.ESTADO_CAJA_CHICA.CERRADA.getValor())) {
                    cont = cont + 1;
                }
            }
            if (tamLista == cont && tamLista >= 1) {
                exito = true;
            }

        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

        return exito;

    }

    @Override
    public void eliminar(ActionEvent actionEvent) {

        try {
            CajaChica cajaChica = servicioCajaChica.conseguirCajaChicaPorId(bkCajaChica.getCajaChicaSeleccionado().getId());

            cajaChica.setEstadoRegistro(ESTADO_REGISTRO.INACTIVO.getValor());
            cajaChica.setUsrModificacion(session.getUsuario().getUsuario());
            cajaChica.setFecModificacion(new Date());
            
            //servicioCajaChica.actualizarCajaChica(cajaChica);
            

            //actualizar el estado del movimiento de de cuenta bancaria, en este caso el cheque que se destina
            //para caja chica 
            //MovimientoCuentaBancaria movCta = servicioMovimientoCuenta.conseguirMovimientoPorId(cajaChica.getIdMovimientoCuentaBancaria().getId());
            cajaChica.getIdMovimientoCuentaBancaria();
            System.out.println("movCta: "+cajaChica.getIdMovimientoCuentaBancaria());
            cajaChica.getIdMovimientoCuentaBancaria().setEstadoMovimiento(MovimientoCuentaBancaria.ESTADO_MOV_CUENTA_BANCARIA.ABIERTO.getValor());
            servicioMovimientoCuenta.actualizarMovCtaBancaria(cajaChica.getIdMovimientoCuentaBancaria());
            
            buscarListaCajaChica();
            mostrarMensaje("Se elimino la caja chica satisfactoriamente");
        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al eliminar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }


    }

    @Override
    public String editar() {

        // Editar caja podemos modificar algunos campos y tambien el estado (cerrar caja)
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void reporteCajaChicaExcel() throws IOException, ServiceException {

        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        Collection<Map<Object, Object>> listaDocumentosResumen = new ArrayList<Map<Object, Object>>();
        //La lista se encuentra desordenada, se debe ordenar las columnas 
        listaDocumentosResumen = reporteCaja(cajaChica);

        HSSFWorkbook wb = new HSSFWorkbook();
        //HSSFWorkbook wb = new HSSFWorkbook(file);        
        HSSFSheet sheet = wb.createSheet("CAJA " + cajaChica.getNombre());

        sheet.setAutobreaks(true);
        sheet.setDefaultColumnWidth(18);
        //sheet.setDefaultRowHeight(Short.valueOf("30"));                
        sheet.setAlternativeFormula(true);
        //sheet.setVerticallyCenter(true);
        sheet.setRowSumsBelow(true);

        HSSFCellStyle borderStyle = wb.createCellStyle();
        borderStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        borderStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        borderStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
        borderStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);

        HSSFCellStyle borderDotStyle = wb.createCellStyle();
        borderDotStyle.setBorderBottom(HSSFCellStyle.BORDER_DOTTED);
        borderDotStyle.setBorderLeft(HSSFCellStyle.BORDER_DOTTED);
        borderDotStyle.setBorderRight(HSSFCellStyle.BORDER_DOTTED);
        borderDotStyle.setBorderTop(HSSFCellStyle.BORDER_DOTTED);
        HSSFPalette palette = wb.getCustomPalette();
        palette.setColorAtIndex(HSSFColor.VIOLET.index, (byte) 153, (byte) 153, (byte) 255);
        /**
         * ***** fuente para titulo ******************
         */
        HSSFFont cabFont = wb.createFont();
        cabFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        cabFont.setFontHeightInPoints(Short.valueOf("10"));

        HSSFCellStyle cabStyle = wb.createCellStyle();
        cabStyle.setFont(cabFont);
        cabStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        /*
         * *** fuente para los datos de cabecera de reporte y cabecera de la tabla resumen
         */
        HSSFFont datosCabFont = wb.createFont();
        datosCabFont.setColor(HSSFColor.WHITE.index);
        datosCabFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        datosCabFont.setFontHeightInPoints(Short.valueOf("8"));

        HSSFCellStyle datosCabStyle = wb.createCellStyle();
        datosCabStyle.cloneStyleFrom(borderStyle);
        datosCabStyle.setFillForegroundColor(HSSFColor.VIOLET.index);
        datosCabStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        datosCabStyle.setFont(datosCabFont);

        /**
         * ***** fuente para total del Importe de caja ******************
         */
        HSSFFont cantFont = wb.createFont();
        cantFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        cantFont.setFontHeightInPoints(Short.valueOf("7"));

        HSSFCellStyle cantStyle = wb.createCellStyle();
        cantStyle.cloneStyleFrom(borderStyle);
        cantStyle.setFont(cantFont);
        /**
         * ***** fuente para detalle de documentos ******************
         */
        HSSFFont contFont = wb.createFont();
        contFont.setFontHeightInPoints(Short.valueOf("7"));

        HSSFCellStyle contenidoStyle = wb.createCellStyle();
        contenidoStyle.cloneStyleFrom(borderDotStyle);
        contenidoStyle.setFont(contFont);
        contenidoStyle.setWrapText(true);
        /*
         *  Fuente para las etiquetas de caja chica (Sede:, Banco:)
         */

        HSSFFont contenFont = wb.createFont();
        contenFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        contenFont.setFontHeightInPoints(Short.valueOf("8"));

        HSSFCellStyle celdaEtiquetaStyle = wb.createCellStyle();
        //celdaStyle.cloneStyleFrom(borderStyle);
        celdaEtiquetaStyle.setFont(contenFont);
        celdaEtiquetaStyle.setWrapText(true);
        /*
         *  Fuente para los valores de cada etiqueta de caja chica (Tararan, Scotiabank)
         */

        HSSFFont contValueFont = wb.createFont();
        contValueFont.setFontHeightInPoints(Short.valueOf("8"));

        HSSFCellStyle celdaValueStyle = wb.createCellStyle();
        //celdaStyle.cloneStyleFrom(borderStyle);
        celdaValueStyle.setFont(contValueFont);
        celdaValueStyle.setWrapText(true);


        HSSFRow rowCab = sheet.createRow(0);
        HSSFCell cellCab0 = rowCab.createCell(2);
        cellCab0.setCellStyle(cabStyle);
        cellCab0.setCellValue("RESUMEN DE CAJA CHICA " + cajaChica.getNombre());
        CellRangeAddress region = new CellRangeAddress(0, 0, 2, 5);
        sheet.addMergedRegion(region);

        //Datos Cabecera de la Caja Chica        
        generarCabeceraReporte(cajaChica, wb, sheet, celdaEtiquetaStyle, celdaValueStyle);
        //Genera la cabecera de la tabla
        generarCabeceraTabla(sheet, datosCabStyle); //sin estilos 

        //Recorrer la coleccion de Map y llenar en las filas posteriores a la cabecera
        int fila = 10;
        //int Columna=0;
        HSSFRow rowDetalle;
        for (Map mapFilaDoc : listaDocumentosResumen) {
            Iterator itr = mapFilaDoc.entrySet().iterator();
            rowDetalle = sheet.createRow(fila);
            while (itr.hasNext()) {
                Map.Entry e = (Map.Entry) itr.next();
                //Metodo que setea en la clumna correcta del excel,el valor presente
                setearValorColumna(wb, rowDetalle, e, contenidoStyle);

                //celda = null;
                //Columna++;                                    
            }
            //Columna = 0;
            fila++;
        }
        //Generacion de la ultima fila para el total del Importe de Caja 
        HSSFDataFormat df = wb.createDataFormat();
        cantStyle.setDataFormat(df.getFormat("0.00"));

        //El total siempre va en la direccion de la columna Importe Soles
        //Total columna 11
        //numero columna 12
        HSSFRow rowTotal;
        rowTotal = sheet.createRow(fila);
        HSSFCell celda = rowTotal.createCell(11);
        celda.setCellStyle(cantStyle);
        celda.setCellValue("TOTAL: ");

        HSSFCell celdaMonto = rowTotal.createCell(12);
        celdaMonto.setCellStyle(cantStyle);
        celdaMonto.setCellValue(cajaChica.getMontoApertura().subtract(cajaChica.getSaldoCaja()).doubleValue());


        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        externalContext.setResponseContentType("application/vnd.ms-excel");
        externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"cajaResumen.xls\"");

        wb.write(externalContext.getResponseOutputStream());
        facesContext.responseComplete();

    }

    public void generarCabeceraTabla(HSSFSheet sheet, HSSFCellStyle datosCabStyle) {

        HSSFRow row = sheet.createRow(9);

        HSSFCell celda = row.createCell(0);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("NOMBRE MOVIMIENTO");

        celda = row.createCell(1);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("FECHA MOVIMIENTO");

        celda = row.createCell(2);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("FECHA SUSTENTO");

        celda = row.createCell(3);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("RUC/DNI");

        celda = row.createCell(4);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("RAZON SOCIAL/NOMBRE");

        celda = row.createCell(5);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("TIPO DOCUMENTO");

        celda = row.createCell(6);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("NUMERO DOCUMENTO");

        celda = row.createCell(7);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("RESPOSABLE");

        celda = row.createCell(8);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("DETALLE");

        celda = row.createCell(9);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("MONEDA");

        celda = row.createCell(10);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("IMPORTE DOLARES");

        celda = row.createCell(11);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("T/C");

        celda = row.createCell(12);
        celda.setCellStyle(datosCabStyle);
        celda.setCellValue("IMPORTE SOLES");
    }

    public void generarCabeceraReporte(CajaChica cajaChica, HSSFWorkbook wb, HSSFSheet sheet,
            HSSFCellStyle etiquetaSyle, HSSFCellStyle valueStyle) {

        int cell = 0;
        HSSFRow row = sheet.createRow(2);
        HSSFCell cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("SEDE: ");

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(valueStyle);
        cel.setCellValue(cajaChica.getIdSede().getNombre());

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("CHEQUE: ");

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(valueStyle);
        cel.setCellValue(cajaChica.getIdMovimientoCuentaBancaria().getNumFormaMovimiento());

        cell = 0;
        row = sheet.createRow(3);
        cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("BANCO: ");

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(valueStyle);
        cel.setCellValue(cajaChica.getIdMovimientoCuentaBancaria().getIdCuentaBancaria().getIdBanco().getNombre());

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("Nº CUENTA BANCARIA: ");

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(valueStyle);
        cel.setCellValue(cajaChica.getIdMovimientoCuentaBancaria().getNumCuentaBancaria());

        cell = 0;
        row = sheet.createRow(4);
        cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("MONTO APERTURA: ");

        cell++;
        cel = row.createCell(cell);
        HSSFDataFormat df = wb.createDataFormat();
        valueStyle.setDataFormat(df.getFormat("0.00"));
        cel.setCellStyle(valueStyle);
        cel.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
        cel.setCellValue(cajaChica.getMontoApertura().doubleValue());

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("FECHA APERTURA: ");

        cell++;
        cel = row.createCell(cell);
        cel.setCellStyle(valueStyle);
        cel.setCellValue(UtilitarioFecha.formatearFecha(cajaChica.getFechaApertura(), "dd/MM/yyyy"));

        cell = 0;
        row = sheet.createRow(5);
        cel = row.createCell(cell);
        cel.setCellStyle(etiquetaSyle);
        cel.setCellValue("SALDO DE CAJA: ");

        cell++;
        cel = row.createCell(cell);
        valueStyle.setDataFormat(df.getFormat("0.00"));
        cel.setCellStyle(valueStyle);
        cel.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
        cel.setCellValue(cajaChica.getSaldoCaja().doubleValue());

    }

    public void setearValorColumna(HSSFWorkbook wb, HSSFRow rowDetalle, Map.Entry atributo, HSSFCellStyle contStyle) {
        HSSFCell celda;
        

        if (atributo.getKey().equals("nombreMov")) {
            System.out.println("nombreMov: "+atributo.getValue());
            celda = rowDetalle.createCell(0);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("fechaMov")) {
            celda = rowDetalle.createCell(1);
            celda.setCellStyle(contStyle);
            String fecha = UtilitarioFecha.formatearFecha((Date) atributo.getValue(), "dd/MM/yyyy");
            celda.setCellValue((String) fecha);
        }
        if (atributo.getKey().equals("fechaDoc")) {
            celda = rowDetalle.createCell(2);
            celda.setCellStyle(contStyle);
            if (atributo.getValue() == null) {
                celda.setCellValue(" ");
            } else {
                String fecha = UtilitarioFecha.formatearFecha((Date) atributo.getValue(), "dd/MM/yyyy");
                celda.setCellValue((String) fecha);
            }
        }
        if (atributo.getKey().equals("rucDNI")) {
            celda = rowDetalle.createCell(3);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("razonSocialNombre")) {
            celda = rowDetalle.createCell(4);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("tipoDocumento")) {
            celda = rowDetalle.createCell(5);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("numeroDocumento")) {
            celda = rowDetalle.createCell(6);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("sustentador")) {
            celda = rowDetalle.createCell(7);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("detalle")) {
            celda = rowDetalle.createCell(8);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("moneda")) {
            celda = rowDetalle.createCell(9);
            celda.setCellStyle(contStyle);
            celda.setCellValue((String) atributo.getValue());
        }
        if (atributo.getKey().equals("importeDolares")) {
            celda = rowDetalle.createCell(10);
            celda.setCellStyle(contStyle);
            if (atributo.getValue() == null) {
                celda.setCellValue(" ");
            } else {
                BigDecimal monto = (BigDecimal) atributo.getValue();
                Double montoDouble = monto.doubleValue();

                HSSFDataFormat df = wb.createDataFormat();

                contStyle.setDataFormat(df.getFormat("0.00"));
                celda.setCellStyle(contStyle);
                celda.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                celda.setCellValue((Double) montoDouble);
            }
            celda.setCellStyle(contStyle);
        }
        if (atributo.getKey().equals("tipoCambio")) {
            celda = rowDetalle.createCell(11);
            
            if (atributo.getValue() == null) {
                celda.setCellValue(" ");
            } else {
                BigDecimal monto = (BigDecimal) atributo.getValue();
                Double montoDouble = monto.doubleValue();

                HSSFDataFormat df = wb.createDataFormat();
                contStyle.setDataFormat(df.getFormat("0.00"));
                celda.setCellStyle(contStyle);
                celda.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                celda.setCellValue((Double) montoDouble);
            }
            celda.setCellStyle(contStyle);
        }
        if (atributo.getKey().equals("importeSoles")) {
            celda = rowDetalle.createCell(12);
            
            if (atributo.getValue() == null) {
                celda.setCellValue(" ");
            } else {
                BigDecimal monto = (BigDecimal) atributo.getValue();
                Double montoDouble = monto.doubleValue();

                HSSFDataFormat df = wb.createDataFormat();
                contStyle.setDataFormat(df.getFormat("0.00"));
                celda.setCellStyle(contStyle);
                celda.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
                celda.setCellValue((Double) montoDouble);
            }
            celda.setCellStyle(contStyle);
        }
    }

    public void buscarFacturas() {

        MovimientoCajaChica movimiento = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();
        try {
            if (movimiento.getSolicitante() != null && !movimiento.getSolicitante().equals(" ")) {
                bkDocumentoSustentador.setMostrarListaFacturas(servicioCompraFacturacion.listarFacturasNoPagadas(movimiento.getSolicitante()));
            } else {
                mostrarError("El nombre del que solicito el movimiento es nulo");
            }
        } catch (ServiceException e) {
            logger.error(e.getMessage(), e);
            mostrarError("Ocurrio un error al cargar la informacion.");
        }

    }

    /*public void cargarFactura() {

     DocumentoSustentador docSustentador = bkDocumentoSustentador.getDocSustentadorFormulario();

     try {
     if (docSustentador.getNumDocumento() != null && !docSustentador.getNumDocumento().equals("0")) {

     CompraFacturacion factura = new CompraFacturacion();
     factura.setIdTipoMoneda(new TipoMoneda());
     factura.setIdProveedor(new Proveedor());
     factura = servicioCompraFacturacion.obtenerFacturaPorNumero(docSustentador.getNumDocumento());
     //Setear algunos campos de la factura obtenido al bkDocumentoSustentador
     bkDocumentoSustentador.getDocSustentadorFormulario().setRucVendedor(factura.getIdProveedor().getRuc());
     bkDocumentoSustentador.getDocSustentadorFormulario().setRazonSocial(factura.getIdProveedor().getRazonSocial());
     bkDocumentoSustentador.getDocSustentadorFormulario().setMoneda(factura.getIdTipoMoneda().getNombre());
     bkDocumentoSustentador.getDocSustentadorFormulario().setFecEmisionRuc(factura.getFecEmision());

     bkDocumentoSustentador.getDocSustentadorFormulario().setTotal(factura.getTotal());

     } else {

     bkDocumentoSustentador.getDocSustentadorFormulario().setRucVendedor(null);
     bkDocumentoSustentador.getDocSustentadorFormulario().setRazonSocial(null);
     bkDocumentoSustentador.getDocSustentadorFormulario().setMoneda(null);
     bkDocumentoSustentador.getDocSustentadorFormulario().setTotal(null);

     }
     } catch (ServiceException e) {
     logger.error(e.getMessage(), e);
     mostrarError("Ocurrio un error al cargar la información.");
     }

     }*/
    public void transferenciaSaldoCajas() {

        // seleccionar las cajas que van a ser transferidas a la caja actual
        // actualizar los saldos de cajas y la caja actual  
        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        CajaChica cajaChicaSalidaDinero = bkCajaChica.getCajaChicaSeleccionado();

        MovimientoCajaChica movimientoEntrada = new MovimientoCajaChica();
        MovimientoCajaChica movimientoSalida = new MovimientoCajaChica();

        BigDecimal montoTransferir = cajaChicaSalidaDinero.getSaldoCaja();


        try {
            // Generar el movimiento de entrada para la cajaChicaEntradaDinero
            movimientoEntrada.setNombre(generarNombreMov(cajaChica));
            movimientoEntrada.setSolicitante("AUTOMÁTICO");
            movimientoEntrada.setMonto(montoTransferir);
            movimientoEntrada.setSaldo(BigDecimal.ZERO);
            movimientoEntrada.setSaldoCaja(cajaChica.getSaldoCaja().add(montoTransferir));
            movimientoEntrada.setEstadoMovimiento(MovimientoCajaChica.ESTADO_MOV_CAJA_CHICA.CERRADO.getValor());
            movimientoEntrada.setFechaCierre(new Date());
            movimientoEntrada.setMotivo("TRANSFERENCIA");
            movimientoEntrada.setDescripcion("Se transfirió el saldo de la caja " + cajaChicaSalidaDinero.getNombre() + " a esta caja");
            movimientoEntrada.setFechaSolicitud(new Date());
            movimientoEntrada.setFecCreacion(new Date());
            movimientoEntrada.setUsrCreacion(session.getUsuario().getUsuario());
            movimientoEntrada.setUnidadNegocio(MovimientoCajaChica.TIPO_UNIDAD_NEGOCIO.NINGUNO.getValor());
            movimientoEntrada.setTipoMovimiento(Constantes.TipoMovimiento.ENTRADA);
            movimientoEntrada.setIdCajaChica(cajaChica);
            movimientoEntrada.setCodigoCajaChica(cajaChicaSalidaDinero.getCodigoCaja());

            // Generar el movimiento de salida para la cajaChicaSalidaDinero
            movimientoSalida.setNombre(generarNombreMov(cajaChicaSalidaDinero));
            movimientoSalida.setSolicitante("AUTOMÁTICO");
            movimientoSalida.setMonto(montoTransferir);
            movimientoSalida.setSaldo(BigDecimal.ZERO);
            movimientoSalida.setSaldoCaja(BigDecimal.ZERO);
            movimientoSalida.setEstadoMovimiento(MovimientoCajaChica.ESTADO_MOV_CAJA_CHICA.CERRADO.getValor());
            movimientoSalida.setFechaCierre(new Date());
            movimientoSalida.setMotivo("TRANSFERENCIA");
            movimientoSalida.setDescripcion("Se transfirió el saldo de esta caja a la caja " + cajaChica.getNombre());
            movimientoSalida.setFechaSolicitud(new Date());
            movimientoSalida.setFecCreacion(new Date());
            movimientoSalida.setUsrCreacion(session.getUsuario().getUsuario());
            movimientoSalida.setUnidadNegocio(MovimientoCajaChica.TIPO_UNIDAD_NEGOCIO.NINGUNO.getValor());
            movimientoSalida.setTipoMovimiento(Constantes.TipoMovimiento.SALIDA);
            movimientoSalida.setIdCajaChica(cajaChicaSalidaDinero);
            movimientoSalida.setCodigoCajaChica(cajaChica.getCodigoCaja());

            // Registrar los movimientos en las cajas respectivas
            servicioMovCajaChica.registrarMovimiento(movimientoEntrada);
            servicioMovCajaChica.registrarMovimiento(movimientoSalida);

            // Actualizar los saldos respectivos de las cajas chicas en mencion
            cajaChica.setSaldoCaja(cajaChica.getSaldoCaja().add(montoTransferir));
            cajaChicaSalidaDinero.setSaldoCaja(BigDecimal.ZERO);

            servicioCajaChica.actualizarCajaChica(cajaChica);
            servicioCajaChica.actualizarCajaChica(cajaChicaSalidaDinero);

            // Refrescar la tabla de movimientos de la caja donde esta ingresando un saldo

            //Refrescar lista de cajas cerradas con saldo 
            bkCajaChica.setMostrarListaCajaChicaConSaldo(this.servicioCajaChica.listarCajaCerradaPorSedeConSaldo(cajaChica));
            mostrarMensaje("Se realizó la transferencia de saldo con éxito");

        } catch (Exception e) {
            mostrarError("Ocurrieron algunos problemas al transferir saldos. Vuelva a intentar.");
            System.err.println(e);
            logger.error(e.getMessage(), e);
        }

    }

    public String nuevaTransferencia() {

        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        //bkCajaChica.setCajaChicaSeleccionado(new CajaChica());
        //bkCajaChica.setTipoCambio(BigDecimal.ZERO);        

        try {
            bkCajaChica.setMostrarListaCajaChicaConSaldo(this.servicioCajaChica.listarCajaCerradaPorSedeConSaldo(cajaChica));

        } catch (ServiceException e) {
            System.out.println(e.getMessage());
            mostrarError("Ocurrieron algunos problemas al actualizar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

        return URLPaginacion.CajaChica.URL_TRANSFERIR_SALDOS;
    }

    public String resumenCajaChica() {

        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        bkCajaChica.setCajaChicaFormulario(cajaChica);

        bkCajaChica.setMostrarResumenCaja(reporteCaja(cajaChica));
        bkMovimientoCajaChica.setVerFormulario(true);

        URL = URLPaginacion.CajaChica.URL_RESUMEN_CAJA_CHICA;
        return URL;
    }

    public Collection<Map<Object, Object>> reporteCaja(CajaChica cajaChica) {

        Collection<Map<Object, Object>> detalleCajaChica = new ArrayList<Map<Object, Object>>();

        //bkMovimientoCajaChica.setListaMovCajaChicaActivas(this.servicioMovCajaChica.listarTodosMovCajaChica(cajaChica));
        try {
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));
        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al ordenar los movimientos. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

        if (!bkMovimientoCajaChica.getListaMovCajaChicaActivas().isEmpty()) {

            for (MovimientoCajaChica mov : this.bkMovimientoCajaChica.getListaMovCajaChicaActivas()) {

                if (!mov.getMotivo().equals("DEVOLUCIÓN DE DINERO")) {

                    bkDocumentoSustentador.setListaTodosDocumentosSustentadores(ordenarDocumentos(mov));
                    if (!bkDocumentoSustentador.getListaTodosDocumentosSustentadores().isEmpty()) {

                        Map<Object, Object> filaDetalle;

                        for (DocumentoSustentador doc : this.bkDocumentoSustentador.getListaTodosDocumentosSustentadores()) {

                            filaDetalle = new HashMap<Object, Object>();
                            System.out.println("nombreMov: "+mov.getNombre());
                            filaDetalle.put("nombreMov", mov.getNombre());
                            filaDetalle.put("fechaMov", mov.getFechaSolicitud());
                            filaDetalle.put("fechaDoc", doc.getFechaSustentacion());
                            filaDetalle.put("rucDNI", doc.getRuc());
                            filaDetalle.put("razonSocialNombre", doc.getRazonSocial());
                            filaDetalle.put("tipoDocumento", doc.getTipoDocumento());
                            filaDetalle.put("numeroDocumento", doc.getNumDocumento());
                            filaDetalle.put("sustentador", mov.getSolicitante());
                            filaDetalle.put("detalle", doc.getConcepto());
                            filaDetalle.put("moneda", doc.getMoneda().getNombre());

                            if (doc.getMoneda().getId() == Constantes.TipoMoneda.DOLARES) {
                                filaDetalle.put("importeDolares", doc.getMontoDocumento());
                                filaDetalle.put("tipoCambio", doc.getTipoCambio());
                                filaDetalle.put("importeSoles", doc.getTotal());
                            } else {
                                filaDetalle.put("importeDolares", null);
                                filaDetalle.put("tipoCambio", null);
                                filaDetalle.put("importeSoles", doc.getTotal());
                            }

                            doc = null;
                            detalleCajaChica.add(filaDetalle);
                            filaDetalle = null;
                        }
                    }
                    mov = null;
                }
            }
        } else {
            detalleCajaChica = null;
        }

        return detalleCajaChica;
    }

    public String regresarToCajaChica() {

        return mostrarMantenimientoMovimientos();
    }

    @Override
    public String aceptar() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String retroceder() {

        // Regresar a la consulta principal de caja chica
        //bkCajaChica.setCajaChicaFormulario(new CajaChica());
        //return mostrarMantenimiento();
        buscarListaCajaChica();
        return URLPaginacion.CajaChica.URL_CONSULTAR_CAJA_CHICA;

    }

    @Override
    public String cancelar() {
        return URLPaginacion.CajaChica.URL_CONSULTAR_CAJA_CHICA;
    }

    //OPERACIONES DEL MOVIMIENTO DE CAJA CHICA
    //############################################
    public String mostrarMantenimientoMovimientos() {

        //CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        try {
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(bkCajaChica.getCajaChicaFormulario()));
        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al ordenar los movimientos. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }
        return URLPaginacion.CajaChica.URL_VER_CAJA_CHICA;
    }

    public Collection<DocumentoSustentador> ordenarDocumentos(MovimientoCajaChica movCajaChica) {

        Collection<DocumentoSustentador> listaOrdenada = new ArrayList<DocumentoSustentador>();
        Collection<DocumentoSustentador> listaDefault = new ArrayList<DocumentoSustentador>();
        ArrayList<Integer> listaIdDocumentos = new ArrayList<Integer>();

        try {

            listaDefault = servicioDocSustentador.listarDocSustentadorActivos(movCajaChica);

            for (DocumentoSustentador docDefault : listaDefault) {
                listaIdDocumentos.add(docDefault.getId());
            }
            //Ordenar lista de id            
            Collections.sort(listaIdDocumentos);

            for (Integer idDoc : listaIdDocumentos) {
                System.out.println("Imprimiendo id del documento:" + idDoc);
                for (DocumentoSustentador docDefault : listaDefault) {
                    if (idDoc == docDefault.getId()) {
                        listaOrdenada.add(docDefault);
                    }
                }
            }

        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al ordenar los documentos sustentadores. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
            listaOrdenada = null;
        }
        return listaOrdenada;
    }

    public String cancelarMovimiento() {

        return mostrarMantenimientoMovimientos();
    }

    public String retrocederDeTransferencia() {

        return mostrarMantenimientoMovimientos();
        //return URLPaginacion.CajaChica.URL_VER_CAJA_CHICA;
    }

    public void eliminarMovimiento(ActionEvent actionEvent) {

        MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();
        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();

        movCajaChica.setEstadoRegistro(ESTADO_REGISTRO.INACTIVO.getValor());
        movCajaChica.setUsrModificacion(session.getUsuario().getUsuario());
        movCajaChica.setFecModificacion(new Date());

        try {

            servicioMovCajaChica.editarMovimiento(movCajaChica);
            
            if(movCajaChica.getTipoMovimiento().equals(Constantes.TipoMovimiento.ENTRADA)){
                cajaChica.setSaldoCaja(
                        cajaChica.getSaldoCaja().subtract(movCajaChica.getMonto()));
            }else{
                cajaChica.setSaldoCaja(
                        cajaChica.getSaldoCaja().add(movCajaChica.getMonto()));
            }
            System.out.println("monto apertura: "+cajaChica.getMontoApertura());
            servicioCajaChica.actualizarCajaChica(cajaChica);
            
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));

            mostrarMensaje("Se elimino el movimiento satisfactoriamente");
        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al eliminar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

    }

    public String nuevoMovimiento() {

        // Se debe tener presente: Monto (Mov) <= Monto Apertura (CajaChica)
        bkMovimientoCajaChica.setVerFormulario(false);
        //bkMovimientoCajaChica.setMovCajaChicaModificar(new MovimientoCajaChica());
        bkMovimientoCajaChica.setMovCajaChicaFormulario(new MovimientoCajaChica());

        // Buscar la fecha del ultimo movimiento realizado en esa caja chica 
        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        Date fechalastMov = new Date();
        fechalastMov = fechaUltimoMovimiento(cajaChica);
        bkMovimientoCajaChica.setFechaMovUltimo(fechalastMov);

        return URLPaginacion.CajaChica.URL_REGISTRAR_MOVIMIENTO;
    }

    public Date fechaUltimoMovimiento(CajaChica cajaChica) {

        Date fechaUltima = new Date();
        int cont = 0;

        try {
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));
            if (!bkMovimientoCajaChica.getListaMovCajaChicaActivas().isEmpty()) {
                for (MovimientoCajaChica mov : bkMovimientoCajaChica.getListaMovCajaChicaActivas()) {
                    if (cont == 0) {
                        fechaUltima = mov.getFechaSolicitud();
                        cont++;
                    } else {
                        if (fechaUltima.before(mov.getFechaSolicitud())) {
                            fechaUltima = mov.getFechaSolicitud();
                        }
                    }
                }
            } else {
                fechaUltima = null;
            }


        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al eliminar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
            fechaUltima = null;
        }

        return fechaUltima;
    }

    public String actualizarMovimiento() {

        MovimientoCajaChica movCajaChicaActual = bkMovimientoCajaChica.getMovCajaChicaFormulario();
        /*MovimientoCajaChica movCajaChicaAntiguo = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();
        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();*/
        
        /*if (cajaChica.getSaldoCaja().compareTo(movCajaChicaActual.getMonto()) == 1
                || cajaChica.getSaldoCaja().compareTo(movCajaChicaActual.getMonto()) == 0) {*/

            try {

                /*movCajaChicaAntiguo.setEstadoMovimiento("A");
                movCajaChicaAntiguo.setIdCajaChica(cajaChica);*/
                /*movCajaChicaAntiguo.setSaldo(movCajaChicaActual.getMonto());
                movCajaChicaAntiguo.setMonto(movCajaChicaActual.getMonto());
                movCajaChicaAntiguo.setSolicitante(movCajaChicaActual.getSolicitante());
                movCajaChicaAntiguo.setUnidadNegocio(movCajaChicaActual.getUnidadNegocio());
                movCajaChicaAntiguo.setMotivo(movCajaChicaActual.getMotivo());
                movCajaChicaAntiguo.setDescripcion(movCajaChicaActual.getDescripcion());
                movCajaChicaAntiguo.setFechaSolicitud(movCajaChicaActual.getFechaSolicitud());*/

                movCajaChicaActual.setUsrModificacion(session.getUsuario().getUsuario());
                movCajaChicaActual.setFecModificacion(new Date());
                /*movCajaChicaAntiguo.setTipoMovimiento("SALIDA");*/

                // Actualizar el saldo de caja chica y actualizamos el mov con el saldo de caja actual
                /*BigDecimal saldoActual;
                saldoActual = cajaChica.getSaldoCaja().subtract(movCajaChicaActual.getMonto());
                movCajaChicaAntiguo.setSaldoCaja(saldoActual);*/
                servicioMovCajaChica.editarMovimiento(movCajaChicaActual);
                /*cajaChica.setSaldoCaja(saldoActual);
                servicioCajaChica.actualizarCajaChica(cajaChica);*/

                //ver si se habilita el Resumen de caja
                //bkCajaChica.setVerResumenCaja(verificaMovCerrados(cajaChica));

                URL = mostrarMantenimientoMovimientos();
                mostrarMensaje("Se actualizó satisfactoriamente los datos del movimiento ");

            } catch (Exception e) {

                mostrarError("Ocurrieron algunos problemas al actualizar la informacion. Vuelva a intentar.");
                System.err.println(e);
                URL = URLPaginacion.CajaChica.URL_EDITAR_MOVIMIENTO;
                logger.error(e.getMessage(), e);
            }

        /*} else {

            mostrarError("El monto del movimiento supera el saldo de caja chica.");
            URL = URLPaginacion.CajaChica.URL_REGISTRAR_MOVIMIENTO;

        }*/

        return URL;

    }

    public String guardarMovimiento() {

        MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaFormulario();
        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();

        if (cajaChica.getSaldoCaja().compareTo(movCajaChica.getMonto()) == 1
                || cajaChica.getSaldoCaja().compareTo(movCajaChica.getMonto()) == 0) {

            try {
                //Guardar nombre de mov, debe ser autogenerado
                movCajaChica.setNombre(generarNombreMov(cajaChica));
                movCajaChica.setEstadoMovimiento(MovimientoCajaChica.ESTADO_MOV_CAJA_CHICA.ABIERTO.getValor());
                movCajaChica.setIdCajaChica(cajaChica);
                movCajaChica.setSaldo(movCajaChica.getMonto());
                movCajaChica.setMontoUsado(BigDecimal.ZERO);
                movCajaChica.setUsrCreacion(session.getUsuario().getUsuario());
                movCajaChica.setFecCreacion(new Date());
                movCajaChica.setTipoMovimiento(Constantes.TipoMovimiento.SALIDA);

                // Actualizar el saldo de caja chica 
                BigDecimal saldoActual;
                saldoActual = cajaChica.getSaldoCaja().subtract(movCajaChica.getMonto());
                cajaChica.setSaldoCaja(saldoActual);

                movCajaChica.setSaldoCaja(saldoActual);

                servicioCajaChica.actualizarCajaChica(cajaChica);
                servicioMovCajaChica.registrarMovimiento(movCajaChica);

                URL = mostrarMantenimientoMovimientos();
                mostrarMensaje("Se guardo satisfactoriamente los datos del movimiento ");

            } catch (Exception e) {

                mostrarError("Ocurrieron algunos problemas al guardar la informacion. Vuelva a intentar.");
                System.err.println(e);
                URL = URLPaginacion.CajaChica.URL_REGISTRAR_MOVIMIENTO;
                logger.error(e.getMessage(), e);
            }

        } else {
            mostrarError("El monto del movimiento supera el saldo de caja chica.");
            URL = URLPaginacion.CajaChica.URL_REGISTRAR_MOVIMIENTO;
        }

        return URL;

    }

    public String generarNombreMov(CajaChica cajaChica) {

        //String nombreBase;
        String nombreCorrelativo = " ";
        //String numeroCaja = " ";

        try {
            bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));
        } catch (ServiceException e) {
            logger.error(e.getMessage(), e);
            mostrarError("Ocurrió un error al cargar la informacion.");
        }

        if (bkMovimientoCajaChica.getListaMovCajaChicaActivas().isEmpty()) {
            nombreCorrelativo = "MOV01";
        } else {
            Integer tam = bkMovimientoCajaChica.getListaMovCajaChicaActivas().size();
            String format = "%1$02d";
            nombreCorrelativo = "MOV" + String.format(format, tam + 1);
        }

        return nombreCorrelativo;
    }

    public String guardarMovBorrador() {

        MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaFormulario();
        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();

        if (cajaChica.getSaldoCaja().compareTo(movCajaChica.getMonto()) == 1
                || cajaChica.getSaldoCaja().compareTo(movCajaChica.getMonto()) == 0) {

            try {


                movCajaChica.setNombre(generarNombreMov(cajaChica));
                movCajaChica.setEstadoMovimiento(MovimientoCajaChica.ESTADO_MOV_CAJA_CHICA.BORRADOR.getValor());
                movCajaChica.setIdCajaChica(cajaChica);
                movCajaChica.setSaldo(movCajaChica.getMonto());
                movCajaChica.setUsrCreacion(session.getUsuario().getUsuario());
                movCajaChica.setFecCreacion(new Date());
                movCajaChica.setTipoMovimiento(Constantes.TipoMovimiento.SALIDA);

                servicioMovCajaChica.registrarMovimiento(movCajaChica);

                bkCajaChica.setVerResumenCaja(verificaMovCerrados(cajaChica));

                URL = mostrarMantenimientoMovimientos();
                mostrarMensaje("Se guardó satisfactoriamente los datos del movimiento ");

            } catch (Exception e) {

                mostrarError("Ocurrieron algunos problemas al guardar la informacion. Vuelva a intentar.");
                System.err.println(e);

                URL = URLPaginacion.CajaChica.URL_REGISTRAR_MOVIMIENTO;
                logger.error(e.getMessage(), e);
            }

        } else {

            mostrarError("El monto del movimiento supera el saldo de caja chica.");
            URL = URLPaginacion.CajaChica.URL_REGISTRAR_MOVIMIENTO;

        }

        return URL;

    }

    public String editarMovimiento() {

        MovimientoCajaChica movCaja = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();
        // La edicion del movimiento solo es posible cuando el estado es: Borrador
        // Cuando el estado del mov es Abierto o Cerrado ya no es posible la edicion ni borrado
        bkMovimientoCajaChica.setMovCajaChicaFormulario(new MovimientoCajaChica());
        bkMovimientoCajaChica.setMovCajaChicaFormulario(movCaja);
        bkMovimientoCajaChica.setMovCajaChicaSeleccionado(bkMovimientoCajaChica.getMovCajaChicaSeleccionado());

        return URLPaginacion.CajaChica.URL_EDITAR_MOVIMIENTO;
    }

    public String cerrarMovimiento() {

        // Solo cerramos mov cuando se encuentre en estado ABIERTO

        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();
        MovimientoCajaChica movCajaChicaEntrada = new MovimientoCajaChica();

        //String movCerrarSolicitante;
        //movCerrarSolicitante = movCajaChica.getSolicitante();
        BigDecimal saldoMovSeleccionado = movCajaChica.getSaldo();


        try {
            //Actualizar el nuevo saldo de la caja chica y registrar un nuevo movimiento
            // de entrada a la caja por el saldo del movimiento cerrado
            if (saldoMovSeleccionado.compareTo(BigDecimal.ZERO) == 1) {

                cajaChica.setSaldoCaja(cajaChica.getSaldoCaja().add(saldoMovSeleccionado));
                servicioCajaChica.actualizarCajaChica(cajaChica);
                //Seteamos el saldo de la caja en el movimiento
                //movCajaChica.setSaldoCaja(cajaChica.getSaldoCaja());

                movCajaChicaEntrada.setId(null);
                movCajaChicaEntrada.setNombre(generarNombreMov(cajaChica));
                movCajaChicaEntrada.setIdCajaChica(cajaChica);

                movCajaChicaEntrada.setSolicitante(movCajaChica.getSolicitante());
                movCajaChicaEntrada.setMonto(saldoMovSeleccionado);

                movCajaChicaEntrada.setSaldo(BigDecimal.ZERO);
                movCajaChicaEntrada.setSaldoCaja(cajaChica.getSaldoCaja());
                movCajaChicaEntrada.setEstadoMovimiento(MovimientoCajaChica.ESTADO_MOV_CAJA_CHICA.CERRADO.getValor());
                movCajaChicaEntrada.setMotivo("DEVOLUCIÓN DE DINERO");
                movCajaChicaEntrada.setDescripcion("Se devuelve el saldo del movimiento " + movCajaChica.getNombre());
                movCajaChicaEntrada.setFechaSolicitud(new Date());
                movCajaChicaEntrada.setFechaCierre(new Date());
                movCajaChicaEntrada.setFecCreacion(new Date());
                movCajaChicaEntrada.setUsrCreacion(session.getUsuario().getUsuario());
                movCajaChicaEntrada.setUnidadNegocio(movCajaChica.getUnidadNegocio());
                movCajaChicaEntrada.setTipoMovimiento(Constantes.TipoMovimiento.ENTRADA);

                servicioMovCajaChica.registrarMovimiento(movCajaChicaEntrada);

            }

            // Actualizando el saldo y estado del movimiento que se cerro
            movCajaChica.setEstadoMovimiento(MovimientoCajaChica.ESTADO_MOV_CAJA_CHICA.CERRADO.getValor());
            movCajaChica.setFechaCierre(new Date());
            movCajaChica.setUsrModificacion(session.getUsuario().getUsuario());
            movCajaChica.setFecModificacion(new Date());
            movCajaChica.setSaldo(BigDecimal.ZERO);

            servicioMovCajaChica.editarMovimiento(movCajaChica);

            //Buscamos si todos los mov estan cerrador para habilitar la opcion de generar reporte
            bkCajaChica.setVerResumenCaja(verificaMovCerrados(cajaChica));

            //bkMovimientoCajaChica.setListaMovCajaChicaActivas(null);
            //bkMovimientoCajaChica.setListaMovCajaChicaActivas(servicioMovCajaChica.listarMovCajaChicaActiva(cajaChica));
            mostrarMensaje("Se cerró el movimiento satisfactoriamente");
            return mostrarMantenimientoMovimientos();

        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al cerrar el movimiento. Vuelva a intentar.");
            logger.error(e.getMessage(), e);

            return URLPaginacion.CajaChica.URL_SUSTENTAR_MOVIMIENTO;
        }

    }

    // OPERACIONES CON EL DOCUMENTO SUSTENTADOR DE MOVIMIENTO
    // ######################################################
    public String sustentarMovimiento() {
        mbComponenteFindProveedor.clearObserver();
        mbComponenteFindProveedor.addObserver(this);
        //MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();
        

        try {
            bkMovimientoCajaChica.setMovCajaChicaSeleccionado(servicioMovCajaChica.conseguirArticuloPorId(bkMovimientoCajaChica.getMovCajaChicaSeleccionado().getId()));
            bkDocumentoSustentador.setListaTodosDocumentosSustentadores(servicioDocSustentador.listarDocSustentadorActivos(bkMovimientoCajaChica.getMovCajaChicaSeleccionado()));
            bkDocumentoSustentador.setListaMonedas(servicioMoneda.listarTipoMonedasActivos());
        } catch (Exception e) {
            mostrarError("Ocurrieron algunos problemas al cargar la informacion. Vuelva a intentar.");
            System.err.println(e);
            logger.error(e.getMessage(), e);
        }

        bkDocumentoSustentador.setVerFormulario(false);
        bkDocumentoSustentador.setDocSustentadorFormulario(new DocumentoSustentador());
        bkDocumentoSustentador.getDocSustentadorFormulario().setMoneda(new TipoMoneda(0));
        //bkDocumentoSustentador.setDocSustentadorSeleccionado(new DocumentoSustentador());
        //bkDocumentoSustentador.getDocSustentadorFormulario().setTipoCambio(BigDecimal.ZERO);      


        return URLPaginacion.CajaChica.URL_SUSTENTAR_MOVIMIENTO;

    }

    public String cancelarSustentoMovimiento() {
        return mostrarMantenimientoMovimientos();
    }

    public void guardarDocumentoSustentador() {

        DocumentoSustentador docSustentador = bkDocumentoSustentador.getDocSustentadorFormulario();
        MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();

        if (movCajaChica.getSaldo().doubleValue() >= docSustentador.getTotal().doubleValue()) {

            try {

                docSustentador.setIdMovimientoCajaChica(movCajaChica);
                docSustentador.setUsrCreacion(session.getUsuario().getUsuario());
                docSustentador.setFecCreacion(new Date());

                servicioDocSustentador.registrarDocSustentador(docSustentador);

                /*if (docSustentador.getTipoDocumento().equals("Factura")) {
                 //Por el numero de documento, actualizamos el estado de la factura: compra_facturacion
                 String numDocumento = docSustentador.getNumDocumento();
                 CompraFacturacion factura = new CompraFacturacion();

                 factura = servicioCompraFacturacion.obtenerFacturaPorNumero(numDocumento);
                 if (factura == null) {
                 mostrarError("No se encontro la factura para actualizar su estado");

                 } else {
                 factura.setEstadoCancelacion('P');
                 factura.setUsrModificacion(session.getUsuario().getUsuario());
                 factura.setFecCancelacion(docSustentador.getFechaSustentacion());
                 factura.setFecModificacion(new Date());
                 servicioCompraFacturacion.actualizarCompraFacturacion(factura);
                 }

                 }*/


                //Actualizamos el saldo del movimiento
                movCajaChica.setSaldo(movCajaChica.getSaldo().subtract(docSustentador.getTotal()));
                movCajaChica.setMontoUsado(movCajaChica.getMontoUsado().add(docSustentador.getTotal()));
                servicioMovCajaChica.editarMovimiento(movCajaChica);
                bkMovimientoCajaChica.setMovCajaChicaSeleccionado(movCajaChica);
                //actualizamos la lista de documentos de la tabla 
                //servicioDocSustentador.actualizarDocSustentador(docSustentador);
                //bkDocumentoSustentador.setListaTodosDocumentosSustentadores(null);
                bkDocumentoSustentador.setListaTodosDocumentosSustentadores(servicioDocSustentador.listarDocSustentadorActivos(movCajaChica));
                //Limpiamos buffer
                //docSustentador = null;
                //bkDocumentoSustentador.setDocSustentadorFormulario(null);
                bkDocumentoSustentador.setDocSustentadorFormulario(new DocumentoSustentador());
                bkDocumentoSustentador.getDocSustentadorFormulario().setMoneda(new TipoMoneda(0));
                //bkDocumentoSustentador.setDocSustentadorSeleccionado(new DocumentoSustentador());

            } catch (Exception e) {

                mostrarError("Ocurrieron algunos problemas al guardar la informacion. Vuelva a intentar.");
                System.err.println(e);
                logger.error(e.getMessage(), e);
            }

        } else {
            mostrarError("El monto del documento excede el saldo del movimiento que falta justificar. Vuelva a intentar");
        }


    }

    public void eliminarDocumentoSustentador(ActionEvent actionEvent) {

        CajaChica cajaChica = bkCajaChica.getCajaChicaFormulario();
        DocumentoSustentador docSustentador = bkDocumentoSustentador.getDocSustentadorSeleccionado();
        MovimientoCajaChica movCajaChica = bkMovimientoCajaChica.getMovCajaChicaSeleccionado();

        docSustentador.setEstadoRegistro(ESTADO_REGISTRO.INACTIVO.getValor());
        docSustentador.setUsrModificacion(session.getUsuario().getUsuario());
        docSustentador.setFecModificacion(new Date());

        try {
            movCajaChica.setSaldo(movCajaChica.getSaldo().add(docSustentador.getTotal()));
            movCajaChica.setMontoUsado(movCajaChica.getMontoUsado().subtract(docSustentador.getTotal()));
            servicioMovCajaChica.editarMovimiento(movCajaChica);
            bkMovimientoCajaChica.setMovCajaChicaSeleccionado(movCajaChica);

            //Actualizar el doc sustentador
            servicioDocSustentador.actualizarDocSustentador(docSustentador);

            bkDocumentoSustentador.setListaTodosDocumentosSustentadores(servicioDocSustentador.listarDocSustentadorActivos(movCajaChica));



        } catch (ServiceException e) {
            mostrarError("Ocurrieron algunos problemas al eliminar la informacion. Vuelva a intentar.");
            logger.error(e.getMessage(), e);
        }

    }

    @Override
    public void actualizarObservador(Object object) {
        if (object instanceof Proveedor) {
            Proveedor proveedor = (Proveedor) object;
            bkDocumentoSustentador.getDocSustentadorFormulario().setIdEntidad(proveedor.getId());
            bkDocumentoSustentador.getDocSustentadorFormulario().setRuc(proveedor.getRuc());
            bkDocumentoSustentador.getDocSustentadorFormulario().setRazonSocial(proveedor.getRazonSocial());
        }
    }

    public void obtenerMontoTotal() {
        if (bkDocumentoSustentador.getDocSustentadorFormulario().getTipoCambio() != null) {
            bkDocumentoSustentador.getDocSustentadorFormulario().setTotal(
                    bkDocumentoSustentador.getDocSustentadorFormulario().getMontoDocumento().multiply(bkDocumentoSustentador.getDocSustentadorFormulario().getTipoCambio()));
        } else {
            if (bkDocumentoSustentador.getDocSustentadorFormulario().getMoneda().getId() == Constantes.TipoMoneda.SOLES) {
                bkDocumentoSustentador.getDocSustentadorFormulario().setTotal(bkDocumentoSustentador.getDocSustentadorFormulario().getMontoDocumento());
            }
        }
    }
    
    public void cambiarMoneda() {
        if (bkDocumentoSustentador.getDocSustentadorFormulario().getMoneda().getId() != Constantes.TipoMoneda.DOLARES) {
            bkDocumentoSustentador.getDocSustentadorFormulario().setTipoCambio(null);
            bkDocumentoSustentador.getDocSustentadorFormulario().setTotal(bkDocumentoSustentador.getDocSustentadorFormulario().getMontoDocumento());
        }
    }
}
